package cerna_pairs;

import java.math.BigDecimal;

public class value_pairs {
	private String RNA_1 = new String();
	private String RNA_2 = new String();
	private	int N;
	private	int K;
	private	int n;
	private	int c;
	private double p;
	
	public value_pairs(String RNA1, String RNA2, int N, int K, int n, int c){
		this.RNA_1 = RNA1;
		this.RNA_2 = RNA2;
		this.N = N;
		this.K = K;
		this.n = n;
		this.c = c;
		this.p = caculate_Phyper(N, K, n ,c);
	}
	
	public value_pairs(String RNA1, String RNA2, int N, int K, int n, int c, double p){
		this.RNA_1 = RNA1;
		this.RNA_2 = RNA2;
		this.N = N;
		this.K = K;
		this.n = n;
		this.c = c;
		this.p = p;
	}
	public value_pairs(){
		this.RNA_1 = "NA";
		this.RNA_2 = "NA";
		this.N = 0;
		this.K = 0;
		this.n = 0;
		this.c = 0;
		this.p = 0;
	}
	
	public String get_RNA_1(){
		String results = RNA_1;
		return results;
	}
	
	public String get_RNA_2(){
		return RNA_2;
	}
	
	public int get_N(){
		return this.N;
	}
	
	public int get_K(){
		return this.K;
	}
	
	public int get_n(){
		return this.n;
	}
	
	public int get_c(){
		return this.c;
	}
	
	public String get_pair(){
		String message = RNA_1 + "\t" + RNA_2 + "\t" + N + "\t"  + K + "\t"+ n + "\t" + c + "\t" + p;
		return message;
	}
	
	public String get_header(){
		String header = "RNA_1\tRNA2\tN\tK\tn\tc\tpֵ值";
		return header;
	}
	
	public double get_p(){
		return this.p;
	}
	
	private static double caculate_Phyper(value_pairs pairs){
		double p = 0;
		p = get_phyper(pairs.get_N(), pairs.get_K(), pairs.get_n(), pairs.get_c());
		
		if(p > 1.0){
			p = 1.0;
		}
		
		return p;
	}
	private static double caculate_Phyper(int N, int K, int n, int c){
		double p = 0;
		p = get_phyper(N, K, n, c);
		if(p > 1.0){
			p = 1.0;
		}
		return p;
	}
	// ���㳬���μ�������
	private static double get_phyper(int N, int K, int n, int c){
		// ��ǿ��ת��intΪdouble���ͣ���������pֵ���Ͼ�pֵ������ҪС����
		double N1 = (double)N;
		double n1 = (double)n;
		double K1 = (double)K;
				
		// ����һ��int��������������K��n�бȽ�С���Ǹ�����������ѭ��
		int end = 0;
		if( K >= n ){
			end = n;
		}else{
			end = K;
		}
		
		/**
		 * ��ʼ��ʽ���㣬�����ѭ��������������c��min(K,n)
		 * ������Ҫע��ʹ��С�ڵ��ڣ�<=�����жϣ�������������ֵ����Ҫ�����㵽��ʽ��
		 * �ڲ����е�ѭ��Ҳ�����
		 * �ڹ�ʽ��N��n֮��ĳ�ȡ���ʣ���i���ܶ����ģ����Ե�������
		 * ��������������Щ����ռ������ֱ�����ΪNn, Ki ,last��Ȼ�����
		 */
		double Nn = get_gailv(N1, n1);
		// System.out.println("Nn:" + Nn);
		double results = 0;
		for(int i = c; i <= end; i++){
			double Ki = get_gailv(K1, (double)i);
			double last = get_gailv((N1 - K1), (n1 -(double)i));
			// System.out.println("���Ki��" + Ki);
			// System.out.println("���last" + last);
			results = results + (Ki * last)/Nn;
		}

		return(results);
	}
	// ���㹫ʽ�еĸ������⣬Ӣ�ﵥ�ʲ��ᣬ�õ�ƴ����Ӧ���൱���������
	private static double get_gailv(double N, double n){
		double jieguo;
		/* ԭ���Ĵ��룬ʹ��ѭ�����㣬�鷳�����õݹ�
		double fenzi = 1.0;
		double fenmu = 1.0;
		for(int i = 1; i <= (int)n; i++){
			fenzi =  fenzi * (N - i + 1);
			fenmu = fenmu * i;
		}
		System.out.println("fenzi:" + fenzi);
		System.out.println("fenmu:" + fenmu);
		jieguo = fenzi/fenmu;
		*/
		/** 
		 * �˴�ʹ����n - 1����Ϊ��������Ϊ�׳˼������N����N - n��֮��Ľ׳�
		 * ���ԣ���(n - 1)��Ϊ�������õ�(N - (n - 1)) = (N - n + 1)���÷��Ϲ�ʽ
		*/ 
			BigDecimal fenzi = jiechengda((int)N, ((int)n - 1));
			BigDecimal fenmu = jiechengda((int)n);
			jieguo = fenzi.divide(fenmu, 8, BigDecimal.ROUND_HALF_EVEN).doubleValue() ;
		
		return(jieguo);
	}
	
	/**
	 * ʹ�õݹ�׳����������
	 * �����һ���׳��Ǵ�N�׳˵�1
	 * �ڶ����Ǵ�N��n��һ���׳ˣ��ǣ�N-n+1���Ľ׳ˣ�ר����Գ�ȡ��������
	 * �������Ͷ���double�����Ѿ���java�ܹ���������������
	 * ʹ��int����������int������̫С���³�����ͨ��double����������170�Ľ׳�
	 * �ٴ�ʹ��BigDecimal����math���У�
	 * ����ʹ��Bigϵ��ʱ��������ʹ�õݹ飬��������Ĺ������ڴ棬���ұ���
	*/
	private static double jiecheng(int N){
		double num = N;
		if(num > 0){
			return num * jiecheng(N - 1);
		}else{
			return 1;
		}
	}
	
	private static double jiecheng(int N, int n){
		double num = N;
		if((n + 1)  > 0){
			return num * jiecheng(N - 1, n - 1);
		}else{
			return 1;
		}
	}
	/**
	 * ����BigDecimal�����ݣ������ҪС��������ʹ��BigDecimal�����Ҵ�ʱ������ֹʹ��
	 * @param N
	 * @return
	 * �½�һ��BigDecimal��������ʼ��Ϊ1�������洢�����ʹ��ѭ������
	 * ����BigDecimal�����ݣ������ҪС��������ʹ��BigDecimal�����Ҵ�ʱ������ֹʹ��
	 * �½�һ��BigDecimal��������ʼ��Ϊ1�������洢�����ʹ��ѭ������
	 * ע��ѭ����һ��Ҫ�Դ��������Ǹ�����������ֵ�����ļ��㲢���ǵ����Ľ�������뵽���У����Ǽ���������ڸ�ֵ
	 * ���ĳ���������һ��Ҫ���BigDecimal.ROUND_HALF_EVEN��������С����λ������������ѭ��С�����ᱨ��
	*/

	private static BigDecimal jiechengda(int N){
		BigDecimal results = BigDecimal.valueOf(1);
		for(int i = 1; i <= N; i++){
			BigDecimal num = BigDecimal.valueOf(i);
			results = results.multiply(num);
		}
		return results;
	}
	
	private static BigDecimal jiechengda(int N, int n){
		BigDecimal num = BigDecimal.valueOf(N);
		BigDecimal results = BigDecimal.ONE;
		for(int i = 1; i <= (n+1); i++){
			BigDecimal var = BigDecimal.valueOf(i);
			BigDecimal NK = num.subtract(var).add(BigDecimal.ONE);
		    results = results.multiply(NK);
		}
		return results;
	}
}
